/*
    DIMVisual-KAAPI, the DIMVisual bundle for KAAPI trace files
    Copyright (c) 2008 Lucas Mello Schnorr <schnorr@gmail.com>

    This file is part of DIMVisual-KAAPI.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "KAAPIConverter.h"
#include <kaapi> /* for the trace and level stuff (identifier) */

@implementation KAAPIConverter (Util)
- (id) convertEventUtilThreadStart: (GEvent *) event
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];

	[ret addObject: [self addPajeSetState: @"CREATED" toState: @"State" time: time container: container]];


	if (conversionType == Thread){
		GFields *f = [event fields];
		
		NSString *destthread = [f fieldWithSimpleStringKey: @"cid-created"];
		if (![cid isEqual: destthread]){
			static long long counter = 0;
        
#ifdef SEARCH_THREAD_NAME
			NSString *sourcethread = [f fieldWithSimpleStringKey: @"thread"];
#else
			NSString *sourcethread = cid;
#endif

			NSString *key = [NSString stringWithFormat: @"%@-%@-%d", sourcethread, destthread, counter++];
			[links setObject: key forKey: destthread];

			PajeStartLink *sl;
			sl = [[PajeStartLink alloc] init];
			[sl setTime: time];
			[sl setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"gid", nil] ids: [NSArray arrayWithObjects: gid, nil]]];
			[sl setSourceContainer: container];
			[sl setEntityType: [provider aliasToName:@"Thread_Start"]];
			[sl setValue: [provider aliasToName: @"criando"]];
			[sl setKey: key];
			[ret addObject: sl];
			[sl release];
        
//		NSLog (@"Source %@, Destination %@ Creating key  %@", sourcethread, destthread, key);
		}else{
			[links setObject: @"none" forKey: destthread];
		}
	}

	[ret autorelease];
	return ret;
}


- (id) convertEventUtilThreadRun: (GEvent *) event
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];

	[ret addObject: [self addPajeSetState: @"RUNNING" toState: @"State" time: time container: container]];


	if (conversionType == Thread){
		GFields *f = [event fields];
		NSString *key = [links objectForKey: [f fieldWithSimpleStringKey: @"cid"]];

		if (key == nil){
			NSLog (@"DIMVisual/ %s Warning: converting EventUtilThreadRun does not have a key for the PajeEndLink event generation of thread %@", __FUNCTION__, cid);
		}else if (![key isEqual: @"none"]){
        
			PajeEndLink *el;
			el = [[PajeEndLink alloc] init];
			[el setTime: time];
			[el setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"gid", nil] ids: [NSArray arrayWithObjects: gid, nil]]];
			[el setDestContainer: container];
			[el setEntityType: [provider aliasToName:@"Thread_Start"]];
			[el setValue: [provider aliasToName: @"criando"]];
			[el setKey: key];
			[ret addObject: el];
			[el release];
		}
	}



	[ret autorelease];
	return ret;
}

- (id) convertEventUtilThreadTerm: (GEvent *) event
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];

	[ret addObject: [self addPajeSetState: @"TERMINATED" toState: @"State" time: time container: container]];

	PajeDestroyContainer *dc = [[PajeDestroyContainer alloc] init];
	[dc setTime: time];
	[dc setContainer: container];

	if (conversionType == Process){
		[dc setType: [provider aliasToName: @"gid"]];
	}else{
		[dc setType: [provider aliasToName: @"cid"]];
	}

	[ret addObject: dc];
	[dc release];

	[ret autorelease];
	return ret;
}

- (BOOL) isEventUtilThreadName
{
	if (atoi([levelid cString]) == Event::TR_UTIL_LEVEL &&
		atoi ([eventid cString]) == Event::UTIL_THREAD_NAME){
		return YES;
	}else{
		return NO;
	}

}

- (id) convertEventUtilThreadName: (GEvent *) event
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];

	GFields *f = [event fields];
	NSString *typeOfThread = [f fieldWithSimpleStringKey: @"name"];
	switch ([typeOfThread intValue]){
		case Event::THREAD_NAME_UNKOWN:
			[names setObject: @"Unkown" forKey: cid];
			break;
		case Event::THREAD_NAME_MAIN_THREAD:
			[names setObject: @"Main" forKey: cid];
			break;
		case Event::THREAD_NAME_SIGNAL_THREAD:
			[names setObject: @"Signal" forKey: cid];
			break;
		case Event::THREAD_NAME_EVENT_THREAD:
			[names setObject: @"Event" forKey: cid];
			break;
		case Event::THREAD_NAME_IODEAMON:
			[names setObject: @"Iodeamon" forKey: cid];
			break;
		case Event::THREAD_NAME_SOCK_SCAVANGER:
			[names setObject: @"Scavanger" forKey: cid];
			break;
		case Event::THREAD_NAME_SOCK_DISPATCHER:
			[names setObject: @"Dispatcher" forKey: cid];
			break;
		case Event::THREAD_NAME_K_PROCESSOR:
			[names setObject: @"Kprocessor" forKey: cid];
			break;
		case Event::THREAD_NAME_K_THREAD:
			[names setObject: @"Kthread" forKey: cid];
			break;
		case Event::THREAD_NAME_TRACE_MANAGER:
			[names setObject: @"TraceManager" forKey: cid];
			break;
		default: 
			[names setObject: @"UnkownDefault" forKey: cid];
			break;
	}
	[ret autorelease];
	return ret;
}


- (id) convertEventUtil: (GEvent *) event
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];

	switch (atoi ([eventid cString])){
		case Event::UTIL_THREAD_START:
			[ret addObjectsFromArray: [self convertEventUtilThreadStart: event]];
			break;
		case Event::UTIL_THREAD_RUN:
			[ret addObjectsFromArray: [self convertEventUtilThreadRun: event]];
			break;
		case Event::UTIL_THREAD_NAME:
			[ret addObjectsFromArray: [self convertEventUtilThreadName: event]];
			break;
		case Event::UTIL_THREAD_YIELDTO: 
			[ret addObject: [self addPajeSetState: @"SUSPENDED" toState: @"State" time: time container: container]];
			break;
		case Event::UTIL_THREAD_TERM:
			[ret addObjectsFromArray: [self convertEventUtilThreadTerm: event]];
			break;
		case Event::UTIL_THREAD_RESUME:
			[ret addObject: [self addPajeSetState: @"RUNNING" toState: @"State" time: time container: container]];
			break;
		case Event::UTIL_PROCESS_INFO:
		case Event::UTIL_PROCESS_NAME:
		case Event::UTIL_PROCESS_BLOC_NAME:
			break;
		default:
			break;
	}

	[ret autorelease];
	return ret;
}
@end
